/**
  ETFAna project, Anyang Normal University && IMP-CAS
  \class ETFTimer2
  \brief a bothly-ended plastic scintillator
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-10-30
  \date 2022-04-26 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-10-30   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021-2024 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#include <cstring>
#include <TClonesArray.h>
#include <TGraph.h>
#include "ETFTimer2.h"
#include "ETFDetectorManager.h"
#include "ETFHPTDCCh.h"
#include "ETFPlaHit.h"
#include "ETFMath.h"
#include "ETFMsg.h"
#include "ETFParaManager.h"

ETFTimer2::ETFTimer2(const char *name, double length) : ETFTimer(name, length){
  const int chId0 = fChIdConfig.as<int>();
  if(chId0 >= 0){
    if(ETFMath::endwith(name, "_v")){ // vme channels
      SetChMap(chId0,   fDetId, true);
      SetChMap(chId0 + 1, fDetId + (2<<8), true);
      // SetChMap(chId0+2, -2, true);
      // SetChMap(chId0+3, -2, true);
    } // end if
    else{ // pxi channels // 0-1-2-3: uv-uh-dv-dh
      SetChMap(chId0,   fDetId); // UV
      SetChMap(chId0 + 1, fDetId + (1<<8)); // UH
      SetChMap(chId0 + 2, fDetId + (2<<8)); // DV
      SetChMap(chId0 + 3, fDetId + (3<<8)); // DH
    } // end else
    if(fQChIdConfig.good()){ // 4-5: uq-dqs
      SetChMap(fQChIdConfig[0].as<int>(), fDetId + (4<<8)); // UQ
      SetChMap(fQChIdConfig[1].as<int>(), fDetId + (5<<8)); // DQ
    } // end if q
  } // end if chid0 > 0
} // end ctor

// initialize the detector
void ETFTimer2::Initialize(){
  ETFTimer::Initialize();
  fHit = nullptr;
} // end member function Initialize

// add the data channel to the detector
void ETFTimer2::Assign(const ETFRawChannel *ch, unsigned uid){
  const int udvh = uid>>8 & 0x7; // 0-1-2-3-4-5: uv-uh-dv-dh-uq-dq
  if(1 == udvh || 3 == udvh) return; // ommit (SFE16) TOT channel

  AddHit(ch, udvh);
} // end member function Assign

void ETFTimer2::AddHit(const ETFRawChannel *ch, int udvh){
  ETFPlaHit *hit = nullptr;
  for(auto p : *fHits){
    ETFPlaHit *h = static_cast<ETFPlaHit *>(p);
    if(0 == h->GetStripId()){ // old strip
      hit = h; continue;
    } // end if
  } // end for
  if(!hit && ch->IsT()){ // create a new strip: Q ch does not trigger this
    hit = static_cast<ETFPlaHit *>(fHits->ConstructedAt(fHits->GetEntriesFast()));
    hit->Initialize();
    hit->SetStripId(0);
    hit->SetLength(fLength);
    static double pos[3]{};
    hit->SetPosition(pos);
    hit->SetDelay(fDelay);
    hit->SetName(GetName());
    TransformToLabRef(hit);
    fIsFired = true;
  } // end if(hit is nullptr)
  if(ch->IsT()) hit->SetTChannel(ch, udvh);
  else hit->SetQChannel(ch, udvh);
} // end member function AddHit

double ETFTimer2::GetTime() const{
  if(!fHits->GetEntriesFast() || !fHit) return -999.;
  return fHit->GetTime();
} // end member function GetTime

// time of the left hand PMT
double ETFTimer2::GetTimeL() const{
  if(!fHits->GetEntriesFast() || !fHit){
    // ETFMsg::Warn("ETFTimer2", "GetTimeL: No hits in Tstop");
    return -999.;
  } // end if
  return fHit->GetTimeL();
} // end member function timeL
// time of the right hand PMT
double ETFTimer2::GetTimeR() const{
  if(!fHits->GetEntriesFast() || !fHit){
    // ETFMsg::Warn("ETFTimer2", "GetTimeR: No hits in Tstop");
    return -999.;
  } // end if
  return fHit->GetTimeR();
} // end member function timeR

// return the fired status of Tstop
int ETFTimer2::GetFiredStatus() const{
  if(!fHits->GetEntriesFast() || !fHit) return -1;
  return fHit->GetFiredStatus();
} // end member function GetFiredStatus

int ETFTimer2::GetHitPosition() const{
  if(!fHits->GetEntriesFast() || !fHit) return -1;
  return fHit->GetHitPosition();
} // end member function GetHitPosition

// add strip to fGDumb
void ETFTimer2::ConstructGraph(){
  if(fGDumb->GetN()) return; // has called

  fGDumb->SetMarkerStyle(28);
  fGDumb->SetMarkerColor(30); // gray
  double p[3]{};
  TransformToLabRef(p);
  fGDumb->SetPoint(0, p[2], p[0]);
} // end member function ConstructGraph

void ETFTimer2::DrawHits(){
  for(const auto &p : *fHits) if(p){
    ETFPlaHit *h = dynamic_cast<ETFPlaHit *>(p);
    h->GetGHit()->SetMarkerStyle(21);
    if(h->GetFiredStatus() == 4) h->Draw();
  } // end for and if
} // end member function DrawHits

void ETFTimer2::PostAssign(){
  ETFTimer::PostAssign();
  fHit = dynamic_cast<ETFPlaHit *>(fHits->At(0));
} // end member function PostAssign
